<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // typeof返回的六个结果
        // string  number  undefined function Object Boolean  Symbol(es6新增)
        // null归object所有，历史遗留性问题


        // function foo() {
        //     bar.apply(null, arguments);
        // }

        // function bar() {
        //     console.log(arguments);
        // }
        // foo(1, 2, 3, 4, 5);




        // var f = (function f() {
        //         return 1;
        //     },
        //     function g() {
        //         return '2';
        //     })();
        // typeof f;
        // 逗号操作符  例：var num = (1,2,3);只打印出最后面的结果




        //              this
        // 1.函数预编译过程this-->window
        // 2.全局作用域里this-->window
        // 3.call/apply可以改变函数运行时this指向
        // 4.obj.function() {}; function()里的this指向object(谁调用的指向谁)
        // 1.
        // function test() {
        //     console.log(this);
        // }
        // test();
        // 2.
        // console.log(this);
        // 3.var name = 'window';
        // var obj = {
        //     name: 'obj',
        //     say: {
        //         console.log(this.name);
        //     }
        // }
        // obj.say.call();//call里面传谁指向谁
        // 4.
        // var obj = {
        //     a: function() {
        //         console.log(this.name)
        //     },
        //     name: 'abc'
        // }
        // obj.a();谁调用方法，this指向谁


        // var x = 1;
        // if (function() {}) {
        //     x += typeof f;
        // }
        // 函数放入括号内，f找不到了，所以是undefined
        // x结果为1undefined




        // null == undefined
        // true
        // null === undefined
        // false
        // isNaN('100')
        // false
        // parseInt('1a') == 1
        // false


        // var name = '222';
        // var a = {
        //     name: '111',
        //     say: function() {
        //         console.log(this.name);
        //     }
        // }
        // var fun = a.say;
        // fun() //在全局执行，this指向window
        // a.say() //a调用say方法执行，this指向object

        // var b = {
        //     name: '333',
        //     say: function(fun) {
        //         fun();
        //     }
        // }
        // b.say(a.say); //把a.say放到b.say执行，没人调用，正常执行，走预编译环节，运行结果为222
        // b.say = a.say; //把a.say赋到b.say上面
        // b.say();

        //             arguments
        // arguments.callee  指向函数自身引用
        // function.caller  返回函数被调用时的环境
        // 标准模式下会报错



        // 10的阶乘
        // var num = (function(n) {
        //     if (n == 1) {
        //         return 1;
        //     }
        //     return n * arguments.callee(n - 1);
        // }(10))
        // console.log(num);



        // function test() {
        //     demo();
        // }

        // function demo() {
        //     console.log(demo.caller);
        // }
        // test();
        // function.caller的作用    打印函数被调用的环境



        // var foo = 123;

        // function print() {
        //     this.foo = 234;
        //     console.log(foo);
        // }
        // new print();
        // print里面的this指向window，覆盖了第一行
        //*若new print();的话,创建了一个新对象,this指向object,不能改变全局上的变量了，结果是123



        // 运行test() 和 new test() 的结果分别是什么 ?
        // var a = 5;

        // function test() {
        //     a = 0;
        //     console.log(a);
        //     console.log(this.a);
        //     var a;
        //     console.log(a);
        // }




        //写出执行结果
        // function print() {
        //     console.log(foo); //undefined  预编译声明提升所以打印第一个foo不报错
        //     var foo = 2;
        //     console.log(foo); //2
        //     console.log(hello); //报错   hello is not defined
        // }
        // print();


        // function print() {
        //     var test;
        //     test();

        //     function test() {
        //         console.log(1);
        //     }
        // }
        // print();


        // function print() {
        //     var x = 1;
        //     if (x == '1') {
        //         console.log('one');
        //     }
        //     if (x === '1') {
        //         console.log('two');
        //     }
        // } //隐式类型转换
        // print();


        // function print() {
        //     var marty = {
        //         name: 'marty',
        //         printName: function() {
        //             console.log(this.name);
        //         }
        //     }
        //     var test1 = {
        //         name: 'test1'
        //     }
        //     var test2 = {
        //         name: 'test2'
        //     }
        //     var test3 = {
        //         name: 'test3'
        //     }
        //     test3.printName = marty.printName;
        //     var printName2 = marty.printName.bind({
        //         name: 123
        //     });
        //     marty.printName.call(test1);
        //     marty.printName.apply(test2);
        //     marty.printName();
        //     printName2();
        //     test3.printName();
        // }
        // print();//so easy!!!



        // var bar = {
        //     a: '002'
        // };

        // function print() {
        //     bar.a = 'a';
        //     Object.prototype.b = 'b';
        //     return function inner() {
        //         console.log(bar.a);
        //         console.log(bar.b);
        //     }
        // }
        // print()(); //第一个括号是返回函数，第二个括号是执行返回的函数
    </script>
</body>

</html>